#include "Firebot.h"
#include "commands.h"

extern void loghex(char *what, unsigned char *buf, int length);

CFirebot::CFirebot()
{
     perror("CFirebot()");
     
     verbose_log = 0;
      sample = 1;// = 1;
      timeout_period = 0;
      
    // fbI2C = new I2C(fbIO.PE->getPORT(), fbIO.PE->getPORT(), 0, 2); //LED test
    
    //SDA LCD0, SCL LCD2
  //   fbI2C = new I2C(fbIO.PA->getPORT(), fbIO.PA->getDDR(), 0, 2); //LCd header
     
     fbCOM2 = new RS232(COM2);
     return;                  
}
CFirebot::~CFirebot()
{
     //delete(fbI2C);
     delete(fbCOM2);
     
     perror("~CFirebot()");
     
    // perror("~CFirebot() done");
     return;                 
}

void CFirebot::process()
{
     unsigned char *buffer = NULL;
     int len = 0;
     

    //printf("ticks\n");
     #define dt 9000
     
    // time(&wtf);
     //gettimeofday(&wtf, NULL);
    // printf("%d %d\n", wtf.tv_sec, wtf.tv_usec);
     /*
     if(sample)
     {
       printf("sample\n");
       sample = 0;
       prev = clock();
               
     }
    //prev.
     dude = clock();
     
     if((dude - prev) >= dt)
     {
        printf("sample dt\n");
        
        timeout_period = 1;
        sample = 1;
                  
     }
     
     */
     len = fbSock.process();
  
     if(len <= 0) 
     {
            printf("timeout or error %d\n", len);
            timeout_flag = 1;
     }// else timeout_flag = 0;
     
     if(fbSock.newDataCheck())
     {      
          
        // toggle = !toggle;
         
         if(verbose_log) 
                         perror("CFirebot::process() DataCheck true");

          fbSock.getData(buffer, len);
          
          if(verbose_log) 
                      loghex("while(1)", buffer, len);
            
          parse_command(buffer, len);
            /*
            //temporary debugging purposes
            if(toggle) {
                  fbIO.PE->set(0);
                  fbI2C->i2c_write(0x70, 0xAA);

            } else {
                  fbIO.PE->clr(0);
                  fbI2C->i2c_write(0x70, 0xFF);
            }

             */
            //fbI2C->i2c_write(0x70, 0xAA);
            
          //  sock_sendAllIO();
          //  fbIO.printAllIO();
            
     }
     
     //sock_sendcommand(SOCKCMD_PREQ);

     fbCOM2->process();
    
     if(timeout_flag) 
     {
          //perror("timeoutflag");
          //if(
          printf("timeout flag %d\n", timeoutc);
          sock_sendcommand(SOCKCMD_EVTKILL);
          EVENT_KILL();
        
          timeout_period = 0;
          sample = 1;
          timeoutc++;
         // timeout_flag = 1;
     } else {
         timeoutc = 0;
     }

       /*  
     if(checkTicks(990000))
     {
          //fbCOM2->process();
          
         sock_sendpacket(SOCKCMD_PREQ, NULL, 0);
     
     }
     */
     return;
}
void CFirebot::parse_command(unsigned char *buffer, int len)
{
     //printf("\tparse_command(): %02X\n", buffer[0]);
     if(timeout_flag == 1 && buffer[0] != SOCKCMD_PACK) 
     {
       printf("Command ignored! Need authentication(SOCKCMD_PACK).\n");
        return;
     }
     
     switch(buffer[0]) 
     {
           case SOCKCMD_REQIO:  
                        sock_sendAllIO();
                        break;
           case SOCKCMD_AUTH:                     
                        break;
           case SOCKCMD_PACK: //host computer active
                       fbCOM2->ping();//send ping to rs232 board to activate interfcace    
                        timeout_flag = 0;
                        break;       
           case SOCKCMD_FWDRS232:
                        fbCOM2->sendData(buffer+1, 7);
                        
                        break;
           default:
                    printf("\t\tunknown command: %02X\n", buffer[0]);
                                                                     
     }
     return;
}
void CFirebot::sock_sendAllIO()
{
     unsigned char buffer[12];
     perror("CFirebot::sock_sendAllIO()");
     
     fbIO.reportAllIO(buffer);
     
     sock_sendpacket(COMMAND_REPORTALLIO, buffer, 12);
     
     return;
}
void CFirebot::sock_sendcommand(unsigned char command) 
{
    // perror("timeoutflagsend command");

     fbSock.sendData(&command, 1);
     
     return;
}

void CFirebot::sock_sendpacket(unsigned char command, unsigned char *buffer, int len)//appends command to buffer of size len, 
{
       if(verbose_log)
                      perror("CFirebot::sock_sendpacket()");
     
     unsigned char *packet;
     
     FIREBOT_HEADER fb_head = {0, "FIREBOT(802.11) v0.1"};         

     //fb_head.version = {"FIREBOT(802.11) v0.1"};
     
     packet = new unsigned char[len+sizeof(fb_head)];
    
     if(packet == NULL)
     {
               perror("\tpacket == NULL");
               return;
     }  


     fb_head.command = command;
  //   fb_head.command = htonl(command);
     
    /*     
     packet[3] = command ;
     packet[2] = command >> 8;
     packet[1] = command >> 16;
     packet[0] = command >> 24;
 */
  //   unsigned char *packet = (unsigned char*)malloc(sizeof(packet));
     memcpy(packet, &fb_head, sizeof(fb_head));
  //   memcpy(packet, &command, sizeof(int));
 /*
     printf("addr: %X\n", packet);
     printf("addr: %X\n", packet+4);
     packet += 4;
     printf("addr: %X\n", packet);
     packet -= 4;
     printf("addr: %X\n", packet);
*/
     if(buffer != NULL)
     {
        memcpy(packet+sizeof(fb_head), (void*)buffer, len);
     }
     
     len += sizeof(fb_head);//appended header
     
     fbSock.sendData(packet, len);
     
     if(packet != NULL) delete[] packet;
     return;
}
void CFirebot::EVENT_KILL() //kill all hardware
{
     //kill_pkt.checksum = 0; 
     /*
     kill_pkt.checksum = kill_pkt.
     for(int i = 1; i < 6; i++)
     {
           kill_pkt.checksum += ((char*)kill_pkt+i);    
     }
     */
               perror("KILL_EVENT()");
     
     kill_pkt.cmd = 'F';
     kill_pkt.ch0duty = 0;
     kill_pkt.ch1duty = 0;
     kill_pkt.OE = 0x55;
     kill_pkt.sol12V = 0;
     kill_pkt.sol24V = 0;
     
     kill_pkt.checksum = kill_pkt.ch0duty + kill_pkt.ch1duty + kill_pkt.OE + kill_pkt.sol12V + kill_pkt.sol24V;
     
     //unsigned char *packet = new unsigned char[sizeof(RS232_PACKET)];
     //if(packet == NULL) return;
     
    // memcpy(packet, &kill_pkt, sizeof(RS232_PACKET));
     
   // fbCOM2->sendData(packet, sizeof(RS232_PACKET));
     fbCOM2->sendData((unsigned char*)&kill_pkt, sizeof(RS232_PACKET));
    
    //delete[](packet);
    
     
}

/*
bool CFirebot::checkTicks(clock_t dt)
{   
     static clock_t prev;
     static bool toggle;
     
     if(toggle == 0) {
             prev = clock();
             toggle = 1;
             timeout_flag = 1; //set flag, to be timedout during the next interval of dt if connection is lost
             
             return false;
     }
     
     if (clock()-prev >= dt) 
     {

       toggle = 0;
       return true;
     }    
     
     return false;
}
*/
/* does not work
bool CFirebot::checkTicks(clock_t dt)
{   
     static clock_t prev;
     static bool toggle;
     
     if(toggle == 0) {
             prev = clock();
             toggle = 1;
             timeout_flag = 1; //set flag, to be timedout during the next interval of dt if connection is lost
             
             return false;
     }
     
     if (clock()-prev >= dt) 
     {
       printf("CFirebot::checkTicks() dt\n");
       
       if(timeout_flag) 
       {
          sock_sendpacket(SOCKCMD_EVTKILL, NULL, 0);
          EVENT_KILL();
          timeout_flag = 0;
         } else {
         
       }
       
       toggle = 0;
       return true;
     }    
     
     return false;
}
*/
